#ifndef __UNIT_H__
#define __UNIT_H__

#define DEFINE_UNIT(_UNIT_, _NAME_) \
const _UNIT_##Unit& \
_UNIT_##Unit::get##_NAME_() \
{\
    static const _UNIT_##Unit unit(_NAME_##_TO_BASE_UNIT,#_NAME_);\
    return unit;\
}
#define DEFINE_UNIT_COMPARE(_UNIT_) \
bool \
unitCompare(const _UNIT_##Unit* lhs, const _UNIT_##Unit* rhs)\
{\
    return ((*lhs) > (*rhs));\
}

#define DEFINE_UNIT_APPEND(_UNIT_) \
    void \
    unitAppend(_UNIT_##UnitSeq& unitSeq, const _UNIT_##Unit& unit) \
    { \
        unitSeq.push_back(&unit);\
        sort(unitSeq.begin(), unitSeq.end(), unitCompare);\
        return;\
    }

#define DEFINE_GET_UNIT_SEQ(_UNIT_) \
    _UNIT_##UnitSeq&\
    getUnitSeq() \
    { \
        static _UNIT_##UnitSeq unitSeq; \
        if(unitSeq.empty()) \
        { \
            unitAppend(unitSeq, TSP); \
            unitAppend(unitSeq, BSP); \
            unitAppend(unitSeq, OZ); \
        } \
        return unitSeq; \
    }

#define DEFINE_UNIT_CLASS(_UNIT_) \
Amount  \
_UNIT_##Unit::convertToBaseUnit(const Amount& length) const \
{\
    return factor_m * length;\
}\
\
Amount \
_UNIT_##Unit::convertFromBaseUnit(const Amount& amountInBase) const\
{\
    return amountInBase / factor_m;\
}\
\
Amount \
_UNIT_##Unit::convertOddmentFromBaseUnit(const Amount& amountInBase) const\
{\
    return amountInBase % factor_m;\
}\
\
bool \
_UNIT_##Unit::operator>(const VolumeUnit& unit) const\
{\
    return factor_m > unit.factor_m;\
}\
\
_UNIT_##Unit::_UNIT_##Unit(const Amount& factor, const string& name) :\
    factor_m(factor), name_m(name)\
{\
}\
\
std::ostream& \
operator<<(std::ostream& out, const _UNIT_##Unit& unit)\
{\
    out << unit.name_m;\
    return out;\
}\

#endif

